package net.scrumtool.controller;

import java.util.ArrayList;
import java.util.Calendar;
import java.util.Date;
import java.util.GregorianCalendar;
import java.util.HashSet;
import java.util.List;
import java.util.Set;

import net.scrumtool.model.Collaborator;
import net.scrumtool.model.Event;
import net.scrumtool.model.Eventtype;
import net.scrumtool.model.Participate;
import net.scrumtool.model.Product;
import net.scrumtool.model.Sprint;
import net.scrumtool.technics.DAO;
import net.scrumtool.technics.LabelProviderSprint;
import net.scrumtool.technics.Utils;
import net.scrumtool.view.EditCollaboratorsSprint;
import net.scrumtool.view.Home;
import net.scrumtool.view.OverviewSprint;

import org.eclipse.jface.viewers.ArrayContentProvider;
import org.eclipse.jface.viewers.LabelProvider;
import org.eclipse.jface.viewers.StructuredSelection;
import org.eclipse.swt.SWT;
import org.eclipse.swt.events.SelectionAdapter;
import org.eclipse.swt.events.SelectionEvent;
import org.eclipse.swt.events.SelectionListener;
import org.eclipse.swt.widgets.DateTime;
import org.eclipse.swt.widgets.MessageBox;

public class Csprint {

	Home view;
	private Sprint sprintActif;
	private List<Sprint> sprints;

	// Array sprints;

	public Csprint(Home view) {
		this.view = view;
	}

	public void init() {
		DAO.checkEventtype();
		sprints = DAO.getSprints();

		view.getGrpSprint().setVisible(false);
		view.getTltmEditSprints().setEnabled(false);
		view.getTltmDeleteSprints().setEnabled(false);
		view.getTltmOpenSprints().setEnabled(false);
		view.getTltmEditCollaboratorsSprint().setEnabled(false);

		view.getTableViewerSprints().setContentProvider(new ArrayContentProvider());
		view.getTableViewerSprints().setLabelProvider(new LabelProviderSprint());
		view.getTableViewerSprints().setInput(sprints);

		// view.getTableViewerColumnSprintName().setLabelProvider(new
		// LabelProvider());
		// view.getTableViewerColumnSprintName().getColumn().set

		view.getComboViewerSprint().setContentProvider(new ArrayContentProvider());
		view.getComboViewerSprint().setLabelProvider(new LabelProvider());
		view.getComboViewerSprint().setInput(DAO.getProducts());

	}

	public void listener(final Collaborator userActif) {

		view.getTltmEditCollaboratorsSprint().addSelectionListener(new SelectionListener() {

			@Override
			public void widgetSelected(SelectionEvent arg0) {
				EditCollaboratorsSprint vAddCollaborators = new EditCollaboratorsSprint();
				CeditCollaboratorsSprint cEditCollaborators = new CeditCollaboratorsSprint(vAddCollaborators);
				vAddCollaborators.init();
				cEditCollaborators.init(sprintActif);
				cEditCollaborators.listener(sprintActif);
				vAddCollaborators.open();

			}

			@Override
			public void widgetDefaultSelected(SelectionEvent arg0) {
				// TODO Auto-generated method stub

			}
		});

		view.getTableSprints().addSelectionListener(new SelectionAdapter() {
			@Override
			public void widgetSelected(SelectionEvent e) {
				StructuredSelection sel = (StructuredSelection) view.getTableViewerSprints().getSelection();
				setSprintActif((Sprint) sel.getFirstElement());

				view.getTltmEditSprints().setEnabled(true);
				view.getTltmDeleteSprints().setEnabled(true);
				view.getTltmOpenSprints().setEnabled(true);
				view.getTltmEditCollaboratorsSprint().setEnabled(true);
				/**** TEST *********/

				view.getLblViewSprints().setText("View sprint");
				view.getGrpSprint().setVisible(true);

				List<Date> dts = new ArrayList<Date>();
				dts = DAO.getDatesOfSprint(sprintActif);

				if (dts.size() > 0) {
					Date startSprint = dts.get(0);

					Date endSprint = dts.get(1);

					Calendar cd = new GregorianCalendar();
					cd.setTime(startSprint);

					view.getdtStartSprint().setDay(cd.get(Calendar.DAY_OF_MONTH));
					view.getdtStartSprint().setMonth(cd.get(Calendar.MONTH));
					view.getdtStartSprint().setYear(cd.get(Calendar.YEAR));

					Calendar cd2 = new GregorianCalendar();
					cd2.setTime(endSprint);

					view.getdtEndSprint().setDay(cd2.get(Calendar.DAY_OF_MONTH));
					view.getdtEndSprint().setMonth(cd2.get(Calendar.MONTH));
					view.getdtEndSprint().setYear(cd2.get(Calendar.YEAR));
				} else {
					view.getdtStartSprint().setDate(1900, 01, 01);
					view.getdtEndSprint().setDate(1900, 01, 01);
				}

				view.getTxtNameSprint().setText(sprintActif.getLabel());

				StructuredSelection sel2 = (StructuredSelection) view.getTableViewerSprints().getSelection();
				Sprint s = (Sprint) sel2.getFirstElement();
				Product p = s.getProduct();
				view.getComboViewerSprint().setSelection(new StructuredSelection(p));

				view.getCbProductsSprints().setEnabled(false);

				view.getBtnSprint().setVisible(false);

				view.getGrpSprint().setEnabled(false);

				/***** ENDTEST ******/
			}
		});

		view.getTltmAddSprints().addSelectionListener(new SelectionListener() {

			@Override
			public void widgetSelected(SelectionEvent arg0) {

				view.getTltmEditSprints().setEnabled(false);
				view.getTltmDeleteSprints().setEnabled(false);
				view.getTltmOpenSprints().setEnabled(false);

				view.getCbProductsSprints().setEnabled(true);
				view.getLblViewSprints().setText("Add sprint");
				view.getGrpSprint().setVisible(true);
				view.getGrpSprint().setEnabled(true);

				view.getTxtNameSprint().setText("");

				view.getBtnSprint().setImage(Utils.getImage(Utils.IMG_ADD));
				view.getBtnSprint().setText("Add this sprint");
				view.getBtnSprint().setVisible(true);
			}

			@Override
			public void widgetDefaultSelected(SelectionEvent arg0) {
				// TODO Auto-generated method stub

			}
		});

		view.getTltmEditSprints().addSelectionListener(new SelectionListener() {

			@Override
			public void widgetSelected(SelectionEvent arg0) {
				view.getLblViewSprints().setText("Edit sprint");
				view.getGrpSprint().setVisible(true);

				List<Date> dts = new ArrayList<Date>();
				dts = DAO.getDatesOfSprint(sprintActif);

				if (dts.size() > 0) {
					Date startSprint = dts.get(0);

					Date endSprint = dts.get(1);

					Calendar cd = new GregorianCalendar();
					cd.setTime(startSprint);

					view.getdtStartSprint().setDay(cd.get(Calendar.DAY_OF_MONTH));
					view.getdtStartSprint().setMonth(cd.get(Calendar.MONTH));
					view.getdtStartSprint().setYear(cd.get(Calendar.YEAR));

					Calendar cd2 = new GregorianCalendar();
					cd2.setTime(endSprint);

					view.getdtEndSprint().setDay(cd2.get(Calendar.DAY_OF_MONTH));
					view.getdtEndSprint().setMonth(cd2.get(Calendar.MONTH));
					view.getdtEndSprint().setYear(cd2.get(Calendar.YEAR));

				} else {
					view.getdtStartSprint().setDate(1900, 01, 01);
					view.getdtEndSprint().setDate(1900, 01, 01);
				}

				view.getTxtNameSprint().setText(sprintActif.getLabel());

				StructuredSelection sel = (StructuredSelection) view.getTableViewerSprints().getSelection();
				Sprint s = (Sprint) sel.getFirstElement();
				Product p = s.getProduct();
				view.getComboViewerSprint().setSelection(new StructuredSelection(p));

				view.getBtnSprint().setVisible(true);
				view.getGrpSprint().setEnabled(true);
				view.getCbProductsSprints().setEnabled(true);
				view.getBtnSprint().setImage(Utils.getImage(Utils.IMG_EDIT));
				view.getBtnSprint().setText("Save this sprint");
				view.getBtnSprint().setVisible(true);
			}

			@Override
			public void widgetDefaultSelected(SelectionEvent arg0) {
				// TODO Auto-generated method stub

			}
		});

		view.getTltmDeleteSprints().addSelectionListener(new SelectionListener() {

			@Override
			public void widgetSelected(SelectionEvent arg0) {

				MessageBox messageBoxSprint = new MessageBox(view.getShell(), SWT.ICON_QUESTION | SWT.YES | SWT.NO);
				messageBoxSprint.setText("SCRUMTOOL");
				messageBoxSprint.setMessage("Do you really want to delete this sprint ?");
				int responseSprint = messageBoxSprint.open();
				if (responseSprint == SWT.YES) {
					DAO.SQLSprint(sprintActif, "delete");
					view.getTableViewerSprints().remove(sprintActif);
					view.getGrpSprint().setVisible(false);
				}

			}

			@Override
			public void widgetDefaultSelected(SelectionEvent arg0) {
				// TODO Auto-generated method stub

			}
		});
		view.getBtnSprint().addSelectionListener(new SelectionListener() {

			@Override
			public void widgetSelected(SelectionEvent arg0) {
				if (view.getBtnSprint().getText() == "Add this sprint") {
					if (view.getTxtNameSprint().getText().equals("") || view.getCbProductsSprints().getText().equals("")) {
						Utils.MsgBox(view.getShell(), "Please complete all fields", "information");
					} else {

						boolean nomUtilise = false;
						for (Sprint sprint : DAO.getSprints()) {
							if (sprint.getLabel().equals(view.getTxtNameSprint().getText())) {
								nomUtilise = true;
							}
						}
						if (nomUtilise == true) {
							Utils.MsgBox(view.getShell(), "A sprint already has this name", "information");
						} else {

							DateTime champStart = view.getdtStartSprint();

							Calendar calendar = new GregorianCalendar();
							calendar.set(champStart.getYear(), champStart.getMonth(), champStart.getDay());

							Date start = new Date();
							start.setTime(calendar.getTimeInMillis());

							DateTime champsFin = view.getdtEndSprint();

							Calendar calendar1 = new GregorianCalendar();
							calendar1.set(champsFin.getYear(), champsFin.getMonth(), champsFin.getDay());

							Date end = new Date();
							end.setTime(calendar1.getTimeInMillis());

							if (checkStartBeforeEnd(start, end)) {
								if (checkDatesDoesntExist(start, end, view.getCbProductsSprints().getText())) {
									Sprint sprint = new Sprint(DAO.getProductByName(view.getCbProductsSprints().getText()), view.getTxtNameSprint().getText(), null, new HashSet<Participate>(0), null);
									DAO.SQLSprint(sprint, "insert");
									insertEvent(sprint);
									sprints.add(sprint);
									// view.getTableViewerSprints().add(sprint);
									// view.getTableViewerSprints().refresh(sprint);
									view.getTableViewerSprints().refresh();
									Utils.MsgBox(view.getShell(), "Sprint was created", "information");
								} else {
									Utils.MsgBox(view.getShell(), "Cannot create sprint, a sprint already exist between this dates.", "error");
								}
							} else {
								Utils.MsgBox(view.getShell(), "The date of begin must be before the date of end.", "error");
							}

						}
					}
				} else {

					sprintActif.setLabel(view.getTxtNameSprint().getText());
					sprintActif.setProduct(DAO.getProductByName(view.getCbProductsSprints().getText()));

					Set<Event> events = sprintActif.getEvents();

					DateTime champStart = view.getdtStartSprint();

					Calendar calendar = new GregorianCalendar();
					calendar.set(champStart.getYear(), champStart.getMonth(), champStart.getDay());

					Date start = new Date();
					start.setTime(calendar.getTimeInMillis());

					DateTime champsFin = view.getdtEndSprint();

					Calendar calendar1 = new GregorianCalendar();
					calendar1.set(champsFin.getYear(), champsFin.getMonth(), champsFin.getDay());

					Date end = new Date();
					end.setTime(calendar1.getTimeInMillis());

					if (checkStartBeforeEnd(start, end)) {
						if (checkDatesDoesntExist(start, end, view.getCbProductsSprints().getText())) {
							if (events.size() == 0) {
								List<Eventtype> eventtypestart = DAO.getEventType("where id=1");

								champStart = view.getdtStartSprint();

								calendar = new GregorianCalendar();
								calendar.set(champStart.getYear(), champStart.getMonth(), champStart.getDay());

								start = new Date();
								start.setTime(calendar.getTimeInMillis());
								List<Eventtype> eventtypeend = DAO.getEventType("where id=2");

								champsFin = view.getdtEndSprint();

								calendar1 = new GregorianCalendar();
								calendar1.set(champsFin.getYear(), champsFin.getMonth(), champsFin.getDay());

								end = new Date();
								end.setTime(calendar1.getTimeInMillis());
								Event eventstart = new Event(sprintActif, eventtypestart.get(0), start);

								DAO.SQLEvent(eventstart, "insert");

								Event eventfin = new Event(sprintActif, eventtypeend.get(0), end);

								DAO.SQLEvent(eventfin, "insert");

							} else {
								for (Event event : events) {
									if (event.getEventtype().getId().equals(1)) {
										champStart = view.getdtStartSprint();

										calendar = new GregorianCalendar();
										calendar.set(champStart.getYear(), champStart.getMonth(), champStart.getDay());

										start = new Date();
										start.setTime(calendar.getTimeInMillis());

										event.setEventDate(start);

										DAO.SQLEvent(event, "update");
									} else if (event.getEventtype().getId().equals(2)) {
										DateTime champEnd = view.getdtEndSprint();

										calendar = new GregorianCalendar();
										calendar.set(champEnd.getYear(), champEnd.getMonth(), champEnd.getDay());

										end = new Date();
										end.setTime(calendar.getTimeInMillis());

										event.setEventDate(end);
										DAO.SQLEvent(event, "update");
									}
								}
							}
						} else {
							Utils.MsgBox(view.getShell(), "Cannot create sprint, a sprint already exist between this dates.", "error");
						}
						// sprintActif.setEvents(events);
						DAO.SQLSprint(sprintActif, "update");
						view.getTableViewerSprints().refresh();
						Utils.MsgBox(view.getShell(), "Sprint was updated", "information");
					} else {
						Utils.MsgBox(view.getShell(), "The date of begin must be before the date of end.", "error");
					}
				}
			}

			@Override
			public void widgetDefaultSelected(SelectionEvent arg0) {
				// TODO Auto-generated method stub

			}
		});

		view.getTltmOpenSprints().addSelectionListener(new SelectionListener() {

			@Override
			public void widgetSelected(SelectionEvent arg0) {
				OverviewSprint overview = new OverviewSprint();
				overview.init();
				CoverviewSprint cOvS = new CoverviewSprint(overview);
				cOvS.listener(userActif);
				cOvS.init(sprintActif);
				view.close();
				overview.open();
			}

			@Override
			public void widgetDefaultSelected(SelectionEvent arg0) {
				// TODO Auto-generated method stub

			}
		});
	}

	public void setSprintActif(Sprint sprintActif) {
		this.sprintActif = sprintActif;
	}

	public void insertEvent(Sprint sprint) {

		List<Eventtype> eventtypestart = DAO.getEventType("where id=1");

		DateTime champStart = view.getdtStartSprint();

		Calendar calendar = new GregorianCalendar();
		calendar.set(champStart.getYear(), champStart.getMonth(), champStart.getDay());

		Date start = new Date();
		start.setTime(calendar.getTimeInMillis());

		List<Eventtype> eventtypeend = DAO.getEventType("where id=2");

		DateTime champsFin = view.getdtEndSprint();

		Calendar calendar1 = new GregorianCalendar();
		calendar1.set(champsFin.getYear(), champsFin.getMonth(), champsFin.getDay());

		Date end = new Date();
		end.setTime(calendar1.getTimeInMillis());

		Event eventstart = new Event(sprint, eventtypestart.get(0), start);
		DAO.SQLEvent(eventstart, "insert");

		Event eventfin = new Event(sprint, eventtypeend.get(0), end);
		DAO.SQLEvent(eventfin, "insert");

	}

	private Boolean checkStartBeforeEnd(Date start, Date end) {
		int nb = start.compareTo(end);

		if (nb == 0) {
			return false;
		} else if (nb > 0) {
			return false;
		} else if (nb < 0) {
			return true;
		}
		return false;
	}

	private Boolean checkDatesDoesntExist(Date start, Date end, String nameProduct) {

		List<Sprint> sprints = DAO.getSprintsByNameProduct(nameProduct);
		Date xstart = null;
		Date xend = null;
		Boolean bool = true;

		for (Sprint s : sprints) {
			xstart = DAO.getDateOfSprint(s, "start");
			xend = DAO.getDateOfSprint(s, "end");

			if (xstart.getTime() <= start.getTime() && xend.getTime() >= start.getTime()) {
				bool = false;
			} else if (xstart.getTime() <= end.getTime() && xend.getTime() >= end.getTime()) {
				bool = false;
			}
		}

		return bool;
	}
}
